﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.ComponentModel;

namespace DMTT.Workflow.Activities.Design
{
    [DefaultProperty("Position")]
    [System.ComponentModel.DesignerCategory("Code")]
	public class TreeViewEx : TreeView
	{
        private TreeViewLinkItemCollection m_linkItems;
        private TreeViewPostionType m_position;

        public TreeViewEx()
        {
            m_linkItems = new TreeViewLinkItemCollection();
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TreeViewLinkItemCollection LinkItems
        {
            get { return m_linkItems; }
            set { m_linkItems = value; }
        }

        [DefaultValue(TreeViewPostionType.Left)]
        public TreeViewPostionType Position
        {
            get { return m_position; }
            set { m_position = value; }
        }

        public event ScrollEventHandler Scroll;
        public delegate void ScrollEventHandler(Object sender, System.EventArgs e);

        protected virtual void OnScroll(System.EventArgs e)
        {
            if (Scroll != null)
            {
                Scroll(this, e);
            }
        }

        protected override void WndProc(ref Message message)
        {
            const int WM_PAINT = 0xf;
            const int WM_VSCROLL = 0x115;
            const int WM_MOUSEWHEEL = 0x020A;

            base.WndProc(ref message);

            switch (message.Msg)
            {
                case WM_PAINT:
                    this.DrawLines(null);
                    break;
                case WM_VSCROLL:
                    this.OnScroll(new EventArgs());
                    break;
                case WM_MOUSEWHEEL:
                    this.OnScroll(new EventArgs());
                    break;
            }
        }

        private void DrawLines(TreeNode parentNode)
        {
            TreeNodeCollection nodes = (parentNode != null) ? parentNode.Nodes : this.Nodes;

            foreach (TreeNode node in nodes)
            {
                if (this.IsLinked(node))
                {
                    Graphics gr = this.CreateGraphics();
                    Rectangle rect = node.Bounds;
                    if (m_position == TreeViewPostionType.Left)
                    {
                        rect.X = node.Bounds.X + (gr.MeasureString(node.Text, this.Font).ToSize().Width);
                        rect.Width = node.Bounds.Width - rect.X;
                        rect.Height = node.Bounds.Height;
                        SolidBrush br = new SolidBrush(Color.DarkGray);
                        Pen p = new Pen(br);
                        p.DashStyle = DashStyle.Dash;
                        int y = node.Bounds.Top + (node.Bounds.Height / 2);
                        gr.DrawLine(p, new Point(rect.X, y), new Point(node.TreeView.Width, y));
                    }
                    else
                    {
                        SolidBrush br = new SolidBrush(Color.DarkGray);
                        Pen p = new Pen(br);
                        p.DashStyle = DashStyle.Dash;
                        int y = node.Bounds.Top + (node.Bounds.Height / 2);
                        gr.DrawLine(p, new Point(0, y), new Point(rect.X - 18, y));
                    }
                    gr.Dispose();
                }
                
                if (node.Nodes.Count > 0)
                {
                    this.DrawLines(node);
                }
            }
        }

        private bool IsLinked(TreeNode node)
        {
            foreach (TreeViewLinkItem item in m_linkItems)
            {
                if (item.SourceNode == node || item.DestinationNode == node)
                {
                    return true;
                }
            }
            return false;
        }
    }

    public enum TreeViewPostionType : int
    {
        Left,
        Right
    }
}
